/*
 * Copyright [2022] [https://www.xiaonuo.vip]
 *
 * Snowy采用APACHE LICENSE 2.0开源协议，您在使用过程中，需要注意以下几点：
 *
 * 1.请不要删除和修改根目录下的LICENSE文件。
 * 2.请不要删除和修改Snowy源码头部的版权声明。
 * 3.本项目代码可免费商业使用，商业使用请保留源码和相关描述文件的项目出处，作者声明等。
 * 4.分发源码时候，请注明软件出处 https://www.xiaonuo.vip
 * 5.不可二次分发开源参与同类竞品，如有想法可联系团队xiaonuobase@qq.com商议合作。
 * 6.若您的项目无法满足以上几点，需要更多功能代码，获取Snowy商业授权许可，请在官网购买授权，地址为 https://www.xiaonuo.vip
 */
package vip.xiaonuo.consumer.modular.structure.role.service.impl;

import cn.dev33.satoken.annotation.SaCheckPermission;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollStreamUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.lang.tree.Tree;
import cn.hutool.core.lang.tree.TreeNode;
import cn.hutool.core.lang.tree.TreeUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.extra.spring.SpringUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import io.swagger.v3.oas.annotations.Operation;
import jakarta.annotation.Resource;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.servlet.mvc.condition.PathPatternsRequestCondition;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;
import vip.xiaonuo.auth.core.util.StpLoginUserUtil;
import vip.xiaonuo.consumer.core.enums.ConsumerBuildInEnum;
import vip.xiaonuo.consumer.core.enums.ConsumerDataTypeEnum;
import vip.xiaonuo.consumer.modular.structure.org.entity.ConsumerOrg;
import vip.xiaonuo.consumer.modular.structure.org.service.ConsumerOrgService;
import vip.xiaonuo.consumer.modular.structure.relation.entity.ConsumerRelation;
import vip.xiaonuo.consumer.modular.structure.resource.entity.ConsumerButton;
import vip.xiaonuo.consumer.modular.structure.role.entity.ConsumerRole;
import vip.xiaonuo.consumer.modular.structure.role.enums.ConsumerRoleCategoryEnum;
import vip.xiaonuo.consumer.modular.structure.role.param.*;
import vip.xiaonuo.consumer.modular.structure.role.result.*;
import vip.xiaonuo.consumer.modular.structure.user.entity.ConsumerUser;
import vip.xiaonuo.consumer.modular.structure.user.param.ConsumerUserIdParam;
import vip.xiaonuo.consumer.modular.structure.user.service.ConsumerUserService;
import vip.xiaonuo.common.enums.CommonSortOrderEnum;
import vip.xiaonuo.common.exception.CommonException;
import vip.xiaonuo.common.listener.CommonDataChangeEventCenter;
import vip.xiaonuo.common.page.CommonPageRequest;
import vip.xiaonuo.consumer.modular.structure.role.mapper.ConsumerRoleMapper;
import vip.xiaonuo.consumer.modular.structure.role.service.ConsumerRoleService;
//import vip.xiaonuo.mobile.vip.MobileMenuApi;
import vip.xiaonuo.consumer.modular.structure.relation.enums.ConsumerRelationCategoryEnum;
import vip.xiaonuo.consumer.modular.structure.relation.service.ConsumerRelationService;
import vip.xiaonuo.consumer.modular.structure.resource.entity.ConsumerMenu;
import vip.xiaonuo.consumer.modular.structure.resource.enums.ConsumerResourceCategoryEnum;
import vip.xiaonuo.consumer.modular.structure.resource.enums.ConsumerResourceMenuTypeEnum;
import vip.xiaonuo.consumer.modular.structure.resource.service.ConsumerButtonService;
import vip.xiaonuo.consumer.modular.structure.resource.service.ConsumerMenuService;
import vip.xiaonuo.consumer.modular.structure.resource.service.ConsumerModuleService;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * 角色管理Service接口实现类
 *
 * @author Mr.wu
 * @date  2024/09/15 21:12
 **/
@Service
public class ConsumerRoleServiceImpl extends ServiceImpl<ConsumerRoleMapper, ConsumerRole> implements ConsumerRoleService {

    @Resource
    private ConsumerRelationService consumerRelationService;

    @Resource
    private ConsumerOrgService consumerOrgService;

    @Resource
    private ConsumerModuleService consumerModuleService;

    @Resource
    private ConsumerMenuService consumerMenuService;

    @Resource
    private ConsumerUserService consumerUserService;

    @Resource
    private ConsumerButtonService consumerButtonService;

//    @Resource
//    private MobileMenuApi mobileMenuApi;

    private List<String> childRoldList = new ArrayList<>();

    @Override
    public Page<ConsumerRole> page(ConsumerRolePageParam consumerRolePageParam) {
        List<ConsumerRole> allRoleList = this.list();
        QueryWrapper<ConsumerRole> queryWrapper = new QueryWrapper<ConsumerRole>().checkSqlInjection();
        // 查询部分字段
        queryWrapper.lambda().select(ConsumerRole::getId, ConsumerRole::getOrgId, ConsumerRole::getName,
            ConsumerRole::getCategory, ConsumerRole::getSortCode);
        if(ObjectUtil.isNotEmpty(consumerRolePageParam.getOrgId())) {
            queryWrapper.lambda().eq(ConsumerRole::getOrgId, consumerRolePageParam.getOrgId());
        }
        if(ObjectUtil.isNotEmpty(consumerRolePageParam.getCategory())) {
            queryWrapper.lambda().eq(ConsumerRole::getCategory, consumerRolePageParam.getCategory());
        }
        if(ObjectUtil.isNotEmpty(consumerRolePageParam.getSearchKey())) {
            queryWrapper.lambda().like(ConsumerRole::getName, consumerRolePageParam.getSearchKey());
        }
        //在此加入上下级过滤判断，即只显示由当前用户角色所创建的下级及子孙级角色，不显示自已的以及自己以上的
        //1、先获取操作员当前角色
        ConsumerUserIdParam consumerUserIdParam = new ConsumerUserIdParam();
        consumerUserIdParam.setId(StpLoginUserUtil.getLoginUser().getId());
        List<String> ownRoleList = consumerUserService.ownRole(consumerUserIdParam);//获取当前用户的角色数组
        childRoldList = new ArrayList<>();
        List<String> childRoleIds =  getChildRole(allRoleList, ownRoleList);//获取下级角色数据
        if(ObjectUtil.isNotEmpty(childRoleIds)){
            queryWrapper.lambda().in(ConsumerRole::getId,childRoleIds);
        }else{
            return new Page<>();
        }
        //2、 排除自己
        queryWrapper.lambda().notIn(ConsumerRole::getId, ownRoleList);
        //数据归属
        queryWrapper.lambda().eq(ConsumerRole::getCompanyId, StpLoginUserUtil.getLoginUser().getCompanyId());
        if(ObjectUtil.isAllNotEmpty(consumerRolePageParam.getSortField(), consumerRolePageParam.getSortOrder())) {
            CommonSortOrderEnum.validate(consumerRolePageParam.getSortOrder());
            queryWrapper.orderBy(true, consumerRolePageParam.getSortOrder().equals(CommonSortOrderEnum.ASC.getValue()),
                StrUtil.toUnderlineCase(consumerRolePageParam.getSortField()));
        } else {
            queryWrapper.lambda().orderByAsc(ConsumerRole::getSortCode);
        }
        return this.page(CommonPageRequest.defaultPage(), queryWrapper);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void add(ConsumerRoleAddParam consumerRoleAddParam) {
        ConsumerRoleCategoryEnum.validate(consumerRoleAddParam.getCategory());
        if(ConsumerRoleCategoryEnum.ORG.getValue().equals(consumerRoleAddParam.getCategory())) {
            if(ObjectUtil.isEmpty(consumerRoleAddParam.getOrgId())) {
                throw new CommonException("orgId不能为空");
            }
        } else {
            consumerRoleAddParam.setOrgId(null);
        }
        ConsumerRole consumerRole = BeanUtil.toBean(consumerRoleAddParam, ConsumerRole.class);
        boolean repeatName = this.count(new LambdaQueryWrapper<ConsumerRole>().eq(ConsumerRole::getOrgId, consumerRole.getOrgId())
            .eq(ConsumerRole::getName, consumerRole.getName())) > 0;
        if(repeatName) {
            if(ObjectUtil.isEmpty(consumerRole.getOrgId())) {
                throw new CommonException("存在重复的全局角色，名称为：{}", consumerRole.getName());
            } else {
                throw new CommonException("同组织下存在重复的角色，名称为：{}", consumerRole.getName());
            }
        }
        //数据归属
        consumerRole.setCompanyId(StpLoginUserUtil.getLoginUser().getCompanyId());
        consumerRole.setCode(RandomUtil.randomString(10));
        ConsumerUserIdParam consumerUserIdParam = new ConsumerUserIdParam();
        consumerUserIdParam.setId(StpLoginUserUtil.getLoginUser().getId());
        consumerRole.setParentId(consumerUserService.ownRole(consumerUserIdParam).get(0));
        this.save(consumerRole);

        // 发布增加事件
        CommonDataChangeEventCenter.doAddWithData(ConsumerDataTypeEnum.ROLE.getValue(), JSONUtil.createArray().put(consumerRole));
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void edit(ConsumerRoleEditParam consumerRoleEditParam) {
        ConsumerRole consumerRole = this.queryEntity(consumerRoleEditParam.getId());
        boolean superRole = consumerRole.getCode().equals(ConsumerBuildInEnum.BUILD_IN_ROLE_CODE.getValue());
        if(superRole) {
            throw new CommonException("不可编辑超管角色");
        }
        if(ConsumerRoleCategoryEnum.ORG.getValue().equals(consumerRoleEditParam.getCategory())) {
            if (ObjectUtil.isEmpty(consumerRoleEditParam.getOrgId())) {
                throw new CommonException("orgId不能为空");
            }
        } else {
            consumerRoleEditParam.setOrgId(null);
        }
        boolean repeatName = this.count(new LambdaQueryWrapper<ConsumerRole>().eq(ConsumerRole::getOrgId, consumerRole.getOrgId())
            .eq(ConsumerRole::getName, consumerRole.getName()).ne(ConsumerRole::getId, consumerRole.getId())) > 0;
        if(repeatName) {
            if(ObjectUtil.isEmpty(consumerRole.getOrgId())) {
                throw new CommonException("存在重复的全局角色，名称为：{}", consumerRole.getName());
            } else {
                throw new CommonException("同组织下存在重复的角色，名称为：{}", consumerRole.getName());
            }
        }
        BeanUtil.copyProperties(consumerRoleEditParam, consumerRole);
        this.updateById(consumerRole);

        // 发布更新事件
        CommonDataChangeEventCenter.doUpdateWithData(ConsumerDataTypeEnum.ROLE.getValue(), JSONUtil.createArray().put(consumerRole));
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void delete(List<ConsumerRoleIdParam> consumerRoleIdParamList) {
        List<String> consumerRoleIdList = CollStreamUtil.toList(consumerRoleIdParamList, ConsumerRoleIdParam::getId);
        if(ObjectUtil.isNotEmpty(consumerRoleIdList)) {
            boolean containsSuperAdminRole = this.listByIds(consumerRoleIdList).stream().map(ConsumerRole::getCode)
                .collect(Collectors.toSet()).contains(ConsumerBuildInEnum.BUILD_IN_ROLE_CODE.getValue());
            if(containsSuperAdminRole) {
                throw new CommonException("不可删除系统内置超管角色");
            }
            // 级联删除角色与用户关系
            consumerRelationService.remove(new LambdaUpdateWrapper<ConsumerRelation>().in(ConsumerRelation::getTargetId, consumerRoleIdList)
                .eq(ConsumerRelation::getCategory, ConsumerRelationCategoryEnum.SYS_USER_HAS_ROLE.getValue()));
            // 级联删除角色与资源关系
            consumerRelationService.remove(new LambdaUpdateWrapper<ConsumerRelation>().in(ConsumerRelation::getObjectId, consumerRoleIdList)
                .eq(ConsumerRelation::getCategory, ConsumerRelationCategoryEnum.SYS_ROLE_HAS_RESOURCE.getValue()));
            // 级联删除角色与权限关系
            consumerRelationService.remove(new LambdaUpdateWrapper<ConsumerRelation>().in(ConsumerRelation::getObjectId, consumerRoleIdList)
                .eq(ConsumerRelation::getCategory, ConsumerRelationCategoryEnum.SYS_ROLE_HAS_PERMISSION.getValue()));
            // 执行删除
            this.removeByIds(consumerRoleIdList);

            // 发布删除事件
            CommonDataChangeEventCenter.doDeleteWithDataId(ConsumerDataTypeEnum.ROLE.getValue(), consumerRoleIdList);
        }
    }

    @Override
    public ConsumerRole detail(ConsumerRoleIdParam consumerRoleIdParam) {
        return this.queryEntity(consumerRoleIdParam.getId());
    }

    @Override
    public ConsumerRoleOwnResourceResult ownResource(ConsumerRoleIdParam consumerRoleIdParam) {
        ConsumerRoleOwnResourceResult consumerRoleOwnResourceResult = new ConsumerRoleOwnResourceResult();
        consumerRoleOwnResourceResult.setId(consumerRoleIdParam.getId());
        consumerRoleOwnResourceResult.setGrantInfoList(consumerRelationService.getRelationListByObjectIdAndCategory(consumerRoleIdParam.getId(),
            ConsumerRelationCategoryEnum.SYS_ROLE_HAS_RESOURCE.getValue()).stream().map(ConsumerRelation ->
            JSONUtil.toBean(ConsumerRelation.getExtJson(), ConsumerRoleOwnResourceResult.ConsumerRoleOwnResource.class)).collect(Collectors.toList()));
        return consumerRoleOwnResourceResult;
    }

    @Override
    public void grantResource(ConsumerRoleGrantResourceParam consumerRoleGrantResourceParam) {
        String id = consumerRoleGrantResourceParam.getId();
        List<String> menuIdList = consumerRoleGrantResourceParam.getGrantInfoList().stream()
                .map(ConsumerRoleGrantResourceParam.ConsumerRoleGrantResource::getMenuId).collect(Collectors.toList());

        List<String> extJsonList = consumerRoleGrantResourceParam.getGrantInfoList().stream()
                .map(JSONUtil::toJsonStr).collect(Collectors.toList());
        //提取menu对应的page权限字符
        List<String> targetList = new ArrayList<>();
        menuIdList.forEach(menuId->{
            ConsumerMenu sysMenu = consumerMenuService.queryEntity(menuId);
            if(ObjectUtil.isNotEmpty(sysMenu.getCode())) {
                List<String> codes = List.of(sysMenu.getCode().split(","));
                codes.forEach(code ->{
                    if(ObjectUtil.isNotEmpty(sysMenu.getPath()) && !targetList.contains(code)){
                        targetList.add("/" + code);
                    }
                });
            }
        });
        //提取按钮对应的权限字符串
        consumerRoleGrantResourceParam.getGrantInfoList().stream().map(ConsumerRoleGrantResourceParam.ConsumerRoleGrantResource::getButtonInfo).forEach((List<String> buttonList)->{
            buttonList.stream().forEach((String buttonId)->{
                ConsumerButton sysButton = consumerButtonService.queryEntity(buttonId);
                if(ObjectUtil.isNotEmpty(sysButton.getComponent())) {
                    List<String> components = List.of(sysButton.getComponent().split(","));
                    components.forEach(component -> {
                        if (ObjectUtil.isNotEmpty(component) && !targetList.contains("/" + component)) {
                            targetList.add("/" + component);
                        }
                    });
                }
            });
        });
        List<String> extJsonListP = new ArrayList<>();
        targetList.forEach(menuAndButtonId->{
            JSONObject ext = new JSONObject();
            List<String> orgList = new ArrayList<>();
            ext.set("apiUrl",menuAndButtonId);
            ext.set("scopeCategory","SCOPE_ALL");
            ext.set("scopeDefineOrgIdList",orgList);
            extJsonListP.add(ext.toString());
        });
        consumerRelationService.saveRelationBatchWithClear(id, menuIdList, ConsumerRelationCategoryEnum.SYS_ROLE_HAS_RESOURCE.getValue(),
                extJsonList);//保存前端资源
        consumerRelationService.saveRelationBatchWithClear(id, targetList, ConsumerRelationCategoryEnum.SYS_ROLE_HAS_PERMISSION.getValue(),
                extJsonListP);//保存后端权限
    }

    @Override
    public ConsumerRoleOwnMobileMenuResult ownMobileMenu(ConsumerRoleIdParam consumerRoleIdParam) {
        ConsumerRoleOwnMobileMenuResult consumerRoleOwnMobileMenuResult = new ConsumerRoleOwnMobileMenuResult();
        consumerRoleOwnMobileMenuResult.setId(consumerRoleIdParam.getId());
        consumerRoleOwnMobileMenuResult.setGrantInfoList(consumerRelationService.getRelationListByObjectIdAndCategory(consumerRoleIdParam.getId(),
            ConsumerRelationCategoryEnum.SYS_ROLE_HAS_MOBILE_MENU.getValue()).stream().map(ConsumerRelation ->
            JSONUtil.toBean(ConsumerRelation.getExtJson(), ConsumerRoleOwnMobileMenuResult.ConsumerRoleOwnMobileMenu.class)).collect(Collectors.toList()));
        return consumerRoleOwnMobileMenuResult;
    }

    @Override
    public void grantMobileMenu(ConsumerRoleGrantMobileMenuParam consumerRoleGrantMobileMenuParam) {
        String id = consumerRoleGrantMobileMenuParam.getId();
        List<String> menuIdList = consumerRoleGrantMobileMenuParam.getGrantInfoList().stream()
            .map(ConsumerRoleGrantMobileMenuParam.ConsumerRoleGrantMobileMenu::getMenuId).collect(Collectors.toList());
        List<String> extJsonList = consumerRoleGrantMobileMenuParam.getGrantInfoList().stream()
            .map(JSONUtil::toJsonStr).collect(Collectors.toList());
        consumerRelationService.saveRelationBatchWithClear(id, menuIdList, ConsumerRelationCategoryEnum.SYS_ROLE_HAS_MOBILE_MENU.getValue(),
            extJsonList);
    }

    @Override
    public ConsumerRoleOwnPermissionResult ownPermission(ConsumerRoleIdParam consumerRoleIdParam) {
        ConsumerRoleOwnPermissionResult consumerRoleOwnPermissionResult = new ConsumerRoleOwnPermissionResult();
        consumerRoleOwnPermissionResult.setId(consumerRoleIdParam.getId());
        consumerRoleOwnPermissionResult.setGrantInfoList(consumerRelationService.getRelationListByObjectIdAndCategory(consumerRoleIdParam.getId(),
            ConsumerRelationCategoryEnum.SYS_ROLE_HAS_PERMISSION.getValue()).stream().map(ConsumerRelation ->
            JSONUtil.toBean(ConsumerRelation.getExtJson(), ConsumerRoleOwnPermissionResult.ConsumerRoleOwnPermission.class)).collect(Collectors.toList()));
        return consumerRoleOwnPermissionResult;
    }

    @Override
    public void grantPermission(ConsumerRoleGrantPermissionParam consumerRoleGrantPermissionParam) {
        String id = consumerRoleGrantPermissionParam.getId();
        List<String> apiUrlList = consumerRoleGrantPermissionParam.getGrantInfoList().stream()
            .map(ConsumerRoleGrantPermissionParam.ConsumerRoleGrantPermission::getApiUrl).collect(Collectors.toList());
        List<String> extJsonList = consumerRoleGrantPermissionParam.getGrantInfoList().stream()
            .map(JSONUtil::toJsonStr).collect(Collectors.toList());
        consumerRelationService.saveRelationBatchWithClear(id, apiUrlList, ConsumerRelationCategoryEnum.SYS_ROLE_HAS_PERMISSION.getValue(),
            extJsonList);
    }

    @Override
    public List<String> ownUser(ConsumerRoleIdParam consumerRoleIdParam) {
        return consumerRelationService.getRelationObjectIdListByTargetIdAndCategory(consumerRoleIdParam.getId(),
            ConsumerRelationCategoryEnum.SYS_USER_HAS_ROLE.getValue());
    }

    @Override
    public void grantUser(ConsumerRoleGrantUserParam consumerRoleGrantUserParam) {
        String id = consumerRoleGrantUserParam.getId();
        List<String> grantInfoList = consumerRoleGrantUserParam.getGrantInfoList();
        consumerRelationService.remove(new LambdaQueryWrapper<ConsumerRelation>().eq(ConsumerRelation::getTargetId, id)
            .eq(ConsumerRelation::getCategory, ConsumerRelationCategoryEnum.SYS_USER_HAS_ROLE.getValue()));
        consumerRelationService.saveBatch(grantInfoList.stream().map(userId -> {
            ConsumerRelation ConsumerRelation = new ConsumerRelation();
            ConsumerRelation.setObjectId(userId);
            ConsumerRelation.setTargetId(id);
            ConsumerRelation.setCategory(ConsumerRelationCategoryEnum.SYS_USER_HAS_ROLE.getValue());
            return ConsumerRelation;
        }).collect(Collectors.toList()));
    }

    @Override
    public ConsumerRole queryEntity(String id) {
        ConsumerRole consumerRole = this.getById(id);
        if(ObjectUtil.isEmpty(consumerRole)) {
            throw new CommonException("角色不存在，id值为：{}", id);
        }
        return consumerRole;
    }

    public List<String> getChildRole(List<ConsumerRole> roleList, List<String> parentRoleIds){
        List<ConsumerRole> newRoles = roleList.stream().filter((item)->{
            return parentRoleIds.contains(item.getParentId());
        }).collect(Collectors.toList());
        if(ObjectUtil.isNotEmpty(newRoles)){
            List<String> newRoleIds = new ArrayList<>();
            for (ConsumerRole consumerRole : newRoles) {
                newRoleIds.add(consumerRole.getId());
            }
            childRoldList.addAll(newRoleIds);
            getChildRole(roleList,newRoleIds);
        }
        return childRoldList;
    }

    /* ====角色部分所需要用到的选择器==== */

    @Override
    public List<Tree<String>> orgTreeSelector() {
        LambdaQueryWrapper<ConsumerOrg> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        List<String> loginUserDataScope = new ArrayList<>();
        StpLoginUserUtil.getLoginUser().getDataScopeList().stream().forEach((dataScope -> {
            loginUserDataScope.addAll(dataScope.getDataScope());
        }));
        // 定义机构集合
        Set<ConsumerOrg> consumerOrgSet = CollectionUtil.newHashSet();
        if (ObjectUtil.isNotEmpty(loginUserDataScope)) {
            // 获取所有机构
            List<ConsumerOrg> allOrgList = consumerOrgService.list();
            loginUserDataScope.forEach(orgId -> consumerOrgSet.addAll(consumerOrgService.getParentListById(allOrgList, orgId, true)));
            List<String> loginUserDataScopeFullList = consumerOrgSet.stream().map(ConsumerOrg::getId).collect(Collectors.toList());
            lambdaQueryWrapper.in(ConsumerOrg::getId, loginUserDataScopeFullList);
        } else {
            return CollectionUtil.newArrayList();
        }
        lambdaQueryWrapper.orderByAsc(ConsumerOrg::getSortCode);
        List<ConsumerOrg> consumerOrgList = consumerOrgService.list(lambdaQueryWrapper);
        List<TreeNode<String>> treeNodeList = consumerOrgList.stream().map(consumerOrg ->
                        new TreeNode<>(consumerOrg.getId(), consumerOrg.getParentId(), consumerOrg.getName(), consumerOrg.getSortCode()))
                .collect(Collectors.toList());
        return TreeUtil.build(treeNodeList, "0");
    }

    @Override
    public List<ConsumerRoleGrantResourceTreeResult> resourceTreeSelector() {
        ConsumerUserIdParam consumerUserIdParam = new ConsumerUserIdParam();
        consumerUserIdParam.setId(StpLoginUserUtil.getLoginUser().getId());
        List<String> ownRoleList = consumerUserService.ownRole(consumerUserIdParam);//获取当前用户的角色数组

        LambdaQueryWrapper<ConsumerMenu> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        List<String> relationIds = new ArrayList<>();
        List<String> buttonInfos = new ArrayList<>();
        List<ConsumerRelation> ownRelationList = consumerRelationService.getRelationListByObjectIdListAndCategory(ownRoleList, ConsumerRelationCategoryEnum.SYS_ROLE_HAS_RESOURCE.getValue());//添加过滤，只显示当前操作角色组所拥有的资料
        List<ConsumerRelation> ownRelationListA = consumerRelationService.getRelationListByObjectIdAndCategory(StpLoginUserUtil.getLoginUser().getId(), ConsumerRelationCategoryEnum.SYS_USER_HAS_RESOURCE.getValue());

        ownRelationList.stream().forEach((item)->{
            relationIds.add(item.getTargetId());
            JSONObject extJson = new JSONObject(item.getExtJson());
            List<String> buttonInfoList = (List<String>) extJson.get("buttonInfo");
            buttonInfoList.forEach(buttonInfo->{
                buttonInfos.add(buttonInfo); //获得授权的所有按钮ID
            });
        });
        ownRelationListA.stream().forEach((item)->{
            relationIds.add(item.getTargetId());
            JSONObject extJson = new JSONObject(item.getExtJson());
            List<String> buttonInfoList = (List<String>) extJson.get("buttonInfo");
            buttonInfoList.forEach(buttonInfo->{
                buttonInfos.add(buttonInfo); //获得授权的所有按钮ID
            });
        });

        lambdaQueryWrapper.and(i->i.in(ConsumerMenu::getId,relationIds).or().in(ConsumerMenu::getCategory, ConsumerResourceCategoryEnum.MODULE.getValue(),//只取在列表中的菜单或不在列表中的model和button以及catalog
                ConsumerResourceCategoryEnum.BUTTON.getValue()).or().in(ConsumerMenu::getMenuType, ConsumerResourceMenuTypeEnum.CATALOG.getValue()));

        List<ConsumerMenu> allMenuAndButtonAndFieldList = consumerMenuService.list(lambdaQueryWrapper);
        List<ConsumerMenu> sysModuleList = CollectionUtil.newArrayList();
        List<ConsumerMenu> sysMenuList = CollectionUtil.newArrayList();
        List<ConsumerMenu> sysButtonList = CollectionUtil.newArrayList();
        allMenuAndButtonAndFieldList.forEach(sysMenu -> {
            //下面的判断针对无授权项目的模块不显示
            if (sysMenu.getCategory().equals(ConsumerResourceCategoryEnum.MODULE.getValue()) && allMenuAndButtonAndFieldList.stream().filter(item ->item.getMenuType()!=null && !item.getMenuType().equals(ConsumerResourceMenuTypeEnum.CATALOG.getValue())).map(ConsumerMenu::getModule).collect(Collectors.toList()).contains(sysMenu.getId()) ) {
                sysModuleList.add(sysMenu);
            }
            if (sysMenu.getCategory().equals(ConsumerResourceCategoryEnum.MENU.getValue())) {
                sysMenuList.add(sysMenu);
            }
            if (sysMenu.getCategory().equals(ConsumerResourceCategoryEnum.BUTTON.getValue()) && buttonInfos.contains(sysMenu.getId())) { //仅添加已获授权的buttonId
                sysButtonList.add(sysMenu);
            }
        });
        List<ConsumerRoleGrantResourceTreeResult.ConsumerRoleGrantResourceMenuResult> leafMenuList = CollectionUtil.newArrayList();
        ConsumerMenu rootSysMenu = new ConsumerMenu();
        rootSysMenu.setId("0");
        rootSysMenu.setParentId("-1");
        rootSysMenu.setSortCode(-1);
        sysMenuList.add(rootSysMenu);
        List<TreeNode<String>> treeNodeList = sysMenuList.stream().map(sysMenu ->
                new TreeNode<>(sysMenu.getId(), sysMenu.getParentId(),
                        sysMenu.getTitle(), sysMenu.getSortCode())).collect(Collectors.toList());
        List<Tree<String>> treeList = TreeUtil.build(treeNodeList, "-1");

        sysMenuList.forEach(sysMenu -> {
            // 排除菜单中的目录
            boolean isLeafMenu = !"0".equals(sysMenu.getId())
                    && !sysMenu.getMenuType().equals(ConsumerResourceMenuTypeEnum.CATALOG.getValue());
            if(isLeafMenu) {
                ConsumerRoleGrantResourceTreeResult.ConsumerRoleGrantResourceMenuResult consumerRoleGrantResourceMenuResult =
                        new ConsumerRoleGrantResourceTreeResult.ConsumerRoleGrantResourceMenuResult();
                BeanUtil.copyProperties(sysMenu, consumerRoleGrantResourceMenuResult);
                JSONObject parentJsonObject = getParentNode(treeList, sysMenu);
                List<String> parentIdSplitList = StrUtil.split(parentJsonObject.getStr("parentId"), StrUtil.DASHED);
                List<String> parentNameSplitList = StrUtil.split(parentJsonObject.getStr("parentName"), StrUtil.DASHED);
                if(parentNameSplitList.size() > 1) {
                    consumerRoleGrantResourceMenuResult.setParentId(parentIdSplitList.get(3));
                    consumerRoleGrantResourceMenuResult.setParentName(parentNameSplitList.get(0));
                    StringBuilder selfNamePrefix = new StringBuilder();
                    for(int i = 1; i< parentNameSplitList.size(); i++) {
                        selfNamePrefix.append(parentNameSplitList.get(i)).append(StrUtil.DASHED);
                    }
                    consumerRoleGrantResourceMenuResult.setTitle(selfNamePrefix + consumerRoleGrantResourceMenuResult.getTitle());
                } else {
                    consumerRoleGrantResourceMenuResult.setParentName(parentJsonObject.getStr("parentName"));
                }
                consumerRoleGrantResourceMenuResult.setButton(this.getChildListById(sysButtonList, sysMenu.getId(), false)
                        .stream().map(sysMenuItem -> {
                            ConsumerRoleGrantResourceTreeResult.ConsumerRoleGrantResourceMenuResult.ConsumerRoleGrantResourceButtonResult
                                    consumerRoleGrantResourceButtonResult = new ConsumerRoleGrantResourceTreeResult
                                    .ConsumerRoleGrantResourceMenuResult.ConsumerRoleGrantResourceButtonResult();
                            BeanUtil.copyProperties(sysMenuItem, consumerRoleGrantResourceButtonResult);
                            return consumerRoleGrantResourceButtonResult;
                        }).collect(Collectors.toList()));
                leafMenuList.add(consumerRoleGrantResourceMenuResult);
            }
        });
        Map<String, List<ConsumerRoleGrantResourceTreeResult.ConsumerRoleGrantResourceMenuResult>> menuListGroup = leafMenuList.stream()
                .collect(Collectors.groupingBy(ConsumerRoleGrantResourceTreeResult.ConsumerRoleGrantResourceMenuResult::getModule));
        return sysModuleList.stream().map(sysModule -> {
            ConsumerRoleGrantResourceTreeResult consumerRoleGrantResourceTreeResult = new ConsumerRoleGrantResourceTreeResult();
            consumerRoleGrantResourceTreeResult.setId(sysModule.getId());
            consumerRoleGrantResourceTreeResult.setTitle(sysModule.getTitle());
            consumerRoleGrantResourceTreeResult.setIcon(sysModule.getIcon());
            consumerRoleGrantResourceTreeResult.setMenu(menuListGroup.get(sysModule.getId()));
            return consumerRoleGrantResourceTreeResult;
        }).collect(Collectors.toList());
    }

//    @Override
//    public List<ConsumerRoleGrantMobileMenuTreeResult> mobileMenuTreeSelector() {
//        return BeanUtil.copyToList(mobileMenuApi.mobileMenuTreeSelector(), ConsumerRoleGrantMobileMenuTreeResult.class);
//    }

    @Override
    public List<String> permissionTreeSelector() {
        List<String> permissionResult = CollectionUtil.newArrayList();
        SpringUtil.getApplicationContext().getBeansOfType(RequestMappingHandlerMapping.class).values()
            .forEach(requestMappingHandlerMapping -> requestMappingHandlerMapping.getHandlerMethods()
                .forEach((key, value) -> {
                    SaCheckPermission saCheckPermission = value.getMethod().getAnnotation(SaCheckPermission.class);
                    if(ObjectUtil.isNotEmpty(saCheckPermission)) {
                        PathPatternsRequestCondition pathPatternsCondition = key.getPathPatternsCondition();
                        if (pathPatternsCondition != null) {
                            String apiName = "未定义接口名称";
                            Operation apiOperation = value.getMethod().getAnnotation(Operation.class);
                            if(ObjectUtil.isNotEmpty(apiOperation)) {
                                String annotationValue = apiOperation.summary();
                                if(ObjectUtil.isNotEmpty(annotationValue)) {
                                    apiName = annotationValue;
                                }
                            }
                            String nm = StrUtil.BRACKET_START + apiName + StrUtil.BRACKET_END;
                            pathPatternsCondition.getPatterns().forEach(pt -> permissionResult.add(pt + nm));
                        }
                    }
                }));
        return CollectionUtil.sortByPinyin(permissionResult.stream().filter(api ->
            !api.startsWith("/" + StrUtil.BRACKET_START)
                && !api.startsWith("/error")
                && !api.contains("/api-docs")
                && !api.contains("/swagger-resources")).collect(Collectors.toList()));
    }

    @Override
    public Page<ConsumerRole> roleSelector(ConsumerRoleSelectorRoleParam consumerRoleSelectorRoleParam) {
        LambdaQueryWrapper<ConsumerRole> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        // 查询部分字段
        lambdaQueryWrapper.select(ConsumerRole::getId, ConsumerRole::getOrgId, ConsumerRole::getName,
            ConsumerRole::getCategory, ConsumerRole::getSortCode);
        if(ObjectUtil.isNotEmpty(consumerRoleSelectorRoleParam.getOrgId())) {
            lambdaQueryWrapper.eq(ConsumerRole::getOrgId, consumerRoleSelectorRoleParam.getOrgId());
        }
        if(ObjectUtil.isNotEmpty(consumerRoleSelectorRoleParam.getCategory())) {
            lambdaQueryWrapper.eq(ConsumerRole::getCategory, consumerRoleSelectorRoleParam.getCategory());
        }
        if(ObjectUtil.isNotEmpty(consumerRoleSelectorRoleParam.getSearchKey())) {
            lambdaQueryWrapper.like(ConsumerRole::getName, consumerRoleSelectorRoleParam.getSearchKey());
        }
        if(ObjectUtil.isNotEmpty(consumerRoleSelectorRoleParam.getDataScopeList())) {
            lambdaQueryWrapper.in(ConsumerRole::getOrgId, consumerRoleSelectorRoleParam.getDataScopeList());
        }

        List<ConsumerRole> allRoleList = this.list(lambdaQueryWrapper);
        // 排除超管角色
        if(consumerRoleSelectorRoleParam.isExcludeSuperAdmin()) {
            lambdaQueryWrapper.ne(ConsumerRole::getCode, ConsumerBuildInEnum.BUILD_IN_ROLE_CODE.getValue());
        }
        //1、先获取操作员当前角色
        ConsumerUserIdParam consumerUserIdParam = new ConsumerUserIdParam();
        consumerUserIdParam.setId(StpLoginUserUtil.getLoginUser().getId());
        List<String> ownRoleList = consumerUserService.ownRole(consumerUserIdParam);//获取当前用户的角色数组
        childRoldList = new ArrayList<>();
        List<String> childRoleIds =  getChildRole(allRoleList, ownRoleList);//获取下级角色数据
        if(ObjectUtil.isNotEmpty(childRoleIds)){
            lambdaQueryWrapper.in(ConsumerRole::getId,childRoleIds);
        }else{
            return new Page<>();
        }
        lambdaQueryWrapper.orderByAsc(ConsumerRole::getSortCode);
        return this.page(CommonPageRequest.defaultPage(), lambdaQueryWrapper);
    }

    @Override
    public Page<ConsumerUser> userSelector(ConsumerRoleSelectorUserParam consumerRoleSelectorUserParam) {
        LambdaQueryWrapper<ConsumerUser> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        // 只查询部分字段
        lambdaQueryWrapper.select(ConsumerUser::getId, ConsumerUser::getAvatar, ConsumerUser::getOrgId, ConsumerUser::getPositionId, ConsumerUser::getAccount,
            ConsumerUser::getName, ConsumerUser::getSortCode, ConsumerUser::getGender, ConsumerUser::getEntryDate);
        //加入防越权授权过滤，即只显示当前操作下级角色用户
        // 排除超管
        lambdaQueryWrapper.ne(ConsumerUser::getAccount, ConsumerBuildInEnum.BUILD_IN_USER_ACCOUNT.getValue());
        //需要排除自己
        lambdaQueryWrapper.ne(ConsumerUser::getId,StpLoginUserUtil.getLoginUser().getId());

        //需要防越级，只能管理角色级别比自己低的人员，先查出全部角色
        LambdaQueryWrapper<ConsumerRole> QueryWrapper = new LambdaQueryWrapper<>();

        List<ConsumerRole> allRoleList = this.list(QueryWrapper);//查询本公司全部角色
        List<String> allRoleIdList = allRoleList.stream().map(ConsumerRole::getId).collect(Collectors.toList());//本公司全部角色ID集合
        //获取操作员当前角色
        ConsumerUserIdParam consumerUserIdParam = new ConsumerUserIdParam();
        consumerUserIdParam.setId(StpLoginUserUtil.getLoginUser().getId());
        List<String> ownRoleList = consumerUserService.ownRole(consumerUserIdParam);//获取当前用户的角色数组
        childRoldList = new ArrayList<>();
        List<String> childRoleIds =  getChildRole(allRoleList, ownRoleList);//获取下级角色数据
        LambdaQueryWrapper<ConsumerRelation> relationLambdaQueryWrapperQueryWrapper = new LambdaQueryWrapper<>();

        LambdaQueryWrapper<ConsumerRelation> allConsumerRelationQueryWrapper = new LambdaQueryWrapper<>();
        if (ObjectUtil.isNotEmpty(allRoleIdList)) {
            allConsumerRelationQueryWrapper.in(ConsumerRelation::getTargetId, allRoleIdList);//本公司已经授权的用户集合
        }
        List<String> allObjectList = consumerRelationService.list(allConsumerRelationQueryWrapper).stream().map(ConsumerRelation::getObjectId).collect(Collectors.toList());
        if (ObjectUtil.isNotEmpty(childRoleIds)) {
            relationLambdaQueryWrapperQueryWrapper.select(ConsumerRelation::getId,ConsumerRelation::getObjectId,ConsumerRelation::getTargetId,ConsumerRelation::getCategory,ConsumerRelation::getExtJson).in(ConsumerRelation::getTargetId,childRoleIds).eq(ConsumerRelation::getCategory, ConsumerRelationCategoryEnum.SYS_USER_HAS_ROLE.getValue());
            List<String> objectList =  consumerRelationService.list(relationLambdaQueryWrapperQueryWrapper).stream().map(ConsumerRelation::getObjectId).collect(Collectors.toList());
            if (ObjectUtil.isNotEmpty(objectList)) {
                if (ObjectUtil.isNotEmpty(allObjectList)) {
                    lambdaQueryWrapper.and(i->i.in(ConsumerUser::getId,objectList).or().notIn(ConsumerUser::getId,allObjectList));
                }else{
                    lambdaQueryWrapper.and(i->i.in(ConsumerUser::getId,objectList));
                }
            }
        }else{
            if (ObjectUtil.isNotEmpty(allObjectList)) {
                lambdaQueryWrapper.and(i -> i.notIn(ConsumerUser::getId, allObjectList));
            }
        }



        // 如果查询条件为空，则直接查询
//        if(ObjectUtil.isAllEmpty(consumerRoleSelectorUserParam.getOrgId(), consumerRoleSelectorUserParam.getSearchKey())) {
//            return consumerUserService.getAllUserSelectorList(lambdaQueryWrapper);
//        } else {
        if (ObjectUtil.isNotEmpty(consumerRoleSelectorUserParam.getOrgId())) {
            // 如果组织id不为空，则查询该组织及其子极其子下的所有人
            List<String> childOrgIdList = CollStreamUtil.toList(consumerOrgService.getChildListById(consumerOrgService
                .getAllOrgList(StpLoginUserUtil.getLoginUser().getCompanyId()), consumerRoleSelectorUserParam.getOrgId(), true), ConsumerOrg::getId);
            if (ObjectUtil.isNotEmpty(childOrgIdList)) {
                lambdaQueryWrapper.in(ConsumerUser::getOrgId, childOrgIdList);
            } else {
                return new Page<>();
            }
        }
        // 排除超管
        lambdaQueryWrapper.ne(ConsumerUser::getAccount, ConsumerBuildInEnum.BUILD_IN_USER_ACCOUNT.getValue());

        if (ObjectUtil.isNotEmpty(consumerRoleSelectorUserParam.getSearchKey())) {
            lambdaQueryWrapper.like(ConsumerUser::getName, consumerRoleSelectorUserParam.getSearchKey());
        }

        lambdaQueryWrapper.orderByAsc(ConsumerUser::getSortCode);

//        }
        return consumerUserService.page(CommonPageRequest.defaultPage(), lambdaQueryWrapper);
    }

    /* ====以下为各种递归方法==== */

    public JSONObject getParentNode(List<Tree<String>> treeList, ConsumerMenu sysMenu) {
        List<Tree<String>> resultList = CollectionUtil.newArrayList();
        getNode(treeList, sysMenu.getId(), resultList);
        JSONObject jsonObject = JSONUtil.createObj();
        if(ObjectUtil.isNotEmpty(resultList)) {
            Tree<String> currentNode = resultList.get(0);
            if("0".equals(currentNode.getId()) || "0".equals(currentNode.getParentId())) {
                jsonObject.set("parentId", sysMenu.getId());
                jsonObject.set("parentName", sysMenu.getTitle());
            } else {
                jsonObject.set("parentId", StrUtil.join(StrUtil.DASHED, CollectionUtil.reverse(CollectionUtil
                    .removeNull(this.getParentsId(currentNode, false)))));
                jsonObject.set("parentName", StrUtil.join(StrUtil.DASHED, CollectionUtil.reverse(CollectionUtil
                    .removeNull(TreeUtil.getParentsName(currentNode, false)))));
            }
        } else {
            jsonObject.set("parentId", sysMenu.getId());
            jsonObject.set("parentName", sysMenu.getTitle());
        }
        return jsonObject;
    }

    public List<String> getParentsId(Tree<String> node, boolean includeCurrentNode) {
        final List<String> result = new ArrayList<>();
        if (null == node) {
            return result;
        }

        if (includeCurrentNode) {
            result.add(node.getId());
        }

        Tree<String> parent = node.getParent();
        while (null != parent) {
            result.add(parent.getId());
            parent = parent.getParent();
        }
        return result;
    }

    public void getNode(List<Tree<String>> treeList, String id, List<Tree<String>> resultList) {
        for (Tree<String> tree: treeList) {
            if(tree.getId().equals(id)) {
                resultList.add(tree);
                break;
            } else {
                List<Tree<String>> children = tree.getChildren();
                if(ObjectUtil.isNotEmpty(children)) {
                    getNode(children, id, resultList);
                }
            }
        }
    }

    public List<ConsumerMenu> getChildListById(List<ConsumerMenu> originDataList, String id, boolean includeSelf) {
        List<ConsumerMenu> sysResourceList = CollectionUtil.newArrayList();
        execRecursionFindChild(originDataList, id, sysResourceList);
        if(includeSelf) {
            ConsumerMenu self = this.getById(originDataList, id);
            if(ObjectUtil.isNotEmpty(self)) {
                sysResourceList.add(self);
            }
        }
        return sysResourceList;
    }

    public List<ConsumerMenu> getParentListById(List<ConsumerMenu> originDataList, String id, boolean includeSelf) {
        List<ConsumerMenu> sysResourceList = CollectionUtil.newArrayList();
        execRecursionFindParent(originDataList, id, sysResourceList);
        if(includeSelf) {
            ConsumerMenu self = this.getById(originDataList, id);
            if(ObjectUtil.isNotEmpty(self)) {
                sysResourceList.add(self);
            }
        }
        return sysResourceList;
    }

    public void execRecursionFindChild(List<ConsumerMenu> originDataList, String id, List<ConsumerMenu> resultList) {
        originDataList.forEach(item -> {
            if(item.getParentId().equals(id)) {
                resultList.add(item);
                execRecursionFindChild(originDataList, item.getId(), resultList);
            }
        });
    }

    public void execRecursionFindParent(List<ConsumerMenu> originDataList, String id, List<ConsumerMenu> resultList) {
        originDataList.forEach(item -> {
            if(item.getId().equals(id)) {
                ConsumerMenu parent = this.getById(originDataList, item.getParentId());
                if(ObjectUtil.isNotEmpty(parent)) {
                    resultList.add(parent);
                }
                execRecursionFindParent(originDataList, item.getParentId(), resultList);
            }
        });
    }

    public ConsumerMenu getById(List<ConsumerMenu> originDataList, String id) {
        int index = CollStreamUtil.toList(originDataList, ConsumerMenu::getId).indexOf(id);
        return index == -1?null:originDataList.get(index);
    }

    public ConsumerMenu getParentById(List<ConsumerMenu> originDataList, String id) {
        ConsumerMenu self = this.getById(originDataList, id);
        return ObjectUtil.isNotEmpty(self)?self:this.getById(originDataList, self.getParentId());
    }

    public ConsumerMenu getChildById(List<ConsumerMenu> originDataList, String id) {
        int index = CollStreamUtil.toList(originDataList, ConsumerMenu::getParentId).indexOf(id);
        return index == -1?null:originDataList.get(index);
    }
}
